use std::process::{Command, Stdio};
use std::path::Path;
use tokio::io::{self, AsyncBufReadExt, BufReader};
use tokio::process::Command as TokioCommand;
use log::{info, error, debug};

// 构建和运行结果
pub struct BuildRunResult {
    pub success: bool,
    pub output: String,
}

// 构建Chym内核
pub async fn build_chym(chym_path: &str) -> BuildRunResult {
    let mut output = String::new();
    output.push_str("开始构建Chym内核...\n");
    
    // 检查构建脚本是否存在
    let build_script = Path::new(chym_path).join(r"scripts\build_and_run.ps1");
    if !build_script.exists() {
        let error_msg = format!("构建脚本不存在: {:?}", build_script);
        error!("{}", error_msg);
        output.push_str(&format!("错误: {}\n", error_msg));
        return BuildRunResult { success: false, output };
    }
    
    output.push_str(&format!("使用构建脚本: {:?}\n", build_script));
    
    // 执行构建命令
    let mut command = TokioCommand::new("powershell.exe");
    command
        .args(["-ExecutionPolicy", "Bypass", "-File", build_script.to_str().unwrap()])
        .current_dir(chym_path)
        .stdout(Stdio::piped())
        .stderr(Stdio::piped());
    
    match command.spawn() {
        Ok(mut child) => {
            // 读取标准输出
            if let Some(stdout) = child.stdout.take() {
                let reader = BufReader::new(stdout);
                let mut lines = reader.lines();
                
                while let Some(line) = lines.next_line().await.unwrap_or(None) {
                    debug!("构建输出: {}", line);
                    output.push_str(&format!("{}\n", line));
                }
            }
            
            // 读取标准错误
            if let Some(stderr) = child.stderr.take() {
                let reader = BufReader::new(stderr);
                let mut lines = reader.lines();
                
                while let Some(line) = lines.next_line().await.unwrap_or(None) {
                    error!("构建错误: {}", line);
                    output.push_str(&format!("错误: {}\n", line));
                }
            }
            
            // 等待命令完成
            let status = child.wait().await.unwrap();
            
            if status.success() {
                output.push_str("\nChym内核构建成功!\n");
                info!("Chym内核构建成功");
                return BuildRunResult { success: true, output };
            } else {
                output.push_str(&format!("\nChym内核构建失败，退出码: {}\n", status.code().unwrap_or(-1)));
                error!("Chym内核构建失败，退出码: {:?}", status.code());
                return BuildRunResult { success: false, output };
            }
        },
        Err(e) => {
            let error_msg = format!("无法执行构建命令: {:?}", e);
            error!("{}", error_msg);
            output.push_str(&format!("错误: {}\n", error_msg));
            return BuildRunResult { success: false, output };
        },
    }
}

// 运行Chym内核
pub async fn run_chym(chym_path: &str) -> BuildRunResult {
    let mut output = String::new();
    output.push_str("开始运行Chym内核...\n");
    
    // 检查运行脚本是否存在
    let run_script = Path::new(chym_path).join(r"scripts\qemu.ps1");
    if !run_script.exists() {
        let error_msg = format!("运行脚本不存在: {:?}", run_script);
        error!("{}", error_msg);
        output.push_str(&format!("错误: {}\n", error_msg));
        return BuildRunResult { success: false, output };
    }
    
    output.push_str(&format!("使用运行脚本: {:?}\n", run_script));
    
    // 执行运行命令
    let mut command = TokioCommand::new("powershell.exe");
    command
        .args(["-ExecutionPolicy", "Bypass", "-File", run_script.to_str().unwrap()])
        .current_dir(chym_path)
        .stdout(Stdio::piped())
        .stderr(Stdio::piped());
    
    match command.spawn() {
        Ok(mut child) => {
            // 读取标准输出
            if let Some(stdout) = child.stdout.take() {
                let reader = BufReader::new(stdout);
                let mut lines = reader.lines();
                
                while let Some(line) = lines.next_line().await.unwrap_or(None) {
                    debug!("运行输出: {}", line);
                    output.push_str(&format!("{}\n", line));
                }
            }
            
            // 读取标准错误
            if let Some(stderr) = child.stderr.take() {
                let reader = BufReader::new(stderr);
                let mut lines = reader.lines();
                
                while let Some(line) = lines.next_line().await.unwrap_or(None) {
                    error!("运行错误: {}", line);
                    output.push_str(&format!("错误: {}\n", line));
                }
            }
            
            // 等待命令完成
            let status = child.wait().await.unwrap();
            
            if status.success() {
                output.push_str("\nChym内核运行完成!\n");
                info!("Chym内核运行完成");
                return BuildRunResult { success: true, output };
            } else {
                output.push_str(&format!("\nChym内核运行失败，退出码: {}\n", status.code().unwrap_or(-1)));
                error!("Chym内核运行失败，退出码: {:?}", status.code());
                return BuildRunResult { success: false, output };
            }
        },
        Err(e) => {
            let error_msg = format!("无法执行运行命令: {:?}", e);
            error!("{}", error_msg);
            output.push_str(&format!("错误: {}\n", error_msg));
            return BuildRunResult { success: false, output };
        },
    }
}

// 检查Chym环境是否配置正确
pub fn check_chym_environment(chym_path: &str) -> BuildRunResult {
    let mut output = String::new();
    output.push_str("检查Chym环境...\n");
    
    // 检查Chym路径是否存在
    let chym_dir = Path::new(chym_path);
    if !chym_dir.exists() {
        let error_msg = format!("Chym路径不存在: {:?}", chym_dir);
        error!("{}", error_msg);
        output.push_str(&format!("错误: {}\n", error_msg));
        return BuildRunResult { success: false, output };
    }
    
    // 检查必要的目录和文件
    let required_dirs = [
        "scripts",
        "src",
        "ChymTD",
        "kernel",
        "ChymDK",
    ];
    
    let required_files = [
        "内核入口.chim",
        r"scripts\build_and_run.ps1",
        r"scripts\qemu.ps1",
        r"scripts\make_iso.ps1",
    ];
    
    let mut missing_dirs = Vec::new();
    let mut missing_files = Vec::new();
    
    for dir in &required_dirs {
        let path = chym_dir.join(dir);
        if !path.exists() {
            missing_dirs.push(path);
        }
    }
    
    for file in &required_files {
        let path = chym_dir.join(file);
        if !path.exists() {
            missing_files.push(path);
        }
    }
    
    if !missing_dirs.is_empty() {
        for dir in &missing_dirs {
            output.push_str(&format!("缺少目录: {:?}\n", dir));
        }
    }
    
    if !missing_files.is_empty() {
        for file in &missing_files {
            output.push_str(&format!("缺少文件: {:?}\n", file));
        }
    }
    
    if missing_dirs.is_empty() && missing_files.is_empty() {
        output.push_str("Chym环境配置正确!\n");
        info!("Chym环境配置正确");
        return BuildRunResult { success: true, output };
    } else {
        output.push_str("Chym环境配置不完整!\n");
        error!("Chym环境配置不完整");
        return BuildRunResult { success: false, output };
    }
}

// 检查QEMU是否安装
pub fn check_qemu_installed() -> bool {
    let output = Command::new("qemu-system-x86_64")
        .arg("--version")
        .output();
    
    match output {
        Ok(output) => {
            if output.status.success() {
                debug!("QEMU已安装: {:?}", String::from_utf8_lossy(&output.stdout));
                return true;
            }
        },
        Err(e) => {
            debug!("QEMU未安装: {:?}", e);
        },
    }
    
    false
}

// 检查Chim编译器是否安装
pub fn check_chim_compiler() -> bool {
    let output = Command::new("chim")
        .arg("--version")
        .output();
    
    match output {
        Ok(output) => {
            if output.status.success() {
                debug!("Chim编译器已安装: {:?}", String::from_utf8_lossy(&output.stdout));
                return true;
            }
        },
        Err(e) => {
            debug!("Chim编译器未安装: {:?}", e);
        },
    }
    
    false
}

// 检查Zig编译器是否安装
pub fn check_zig_compiler() -> bool {
    let output = Command::new("zig")
        .arg("--version")
        .output();
    
    match output {
        Ok(output) => {
            if output.status.success() {
                debug!("Zig编译器已安装: {:?}", String::from_utf8_lossy(&output.stdout));
                return true;
            }
        },
        Err(e) => {
            debug!("Zig编译器未安装: {:?}", e);
        },
    }
    
    false
}
